Completed
Push — master ( 7b524c...0d3c7c )
by Ruben de
05:15 queued 02:24
created

wallet.test.js ➔ ... ➔ createTransactionTestWallet   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
c 3
b 0
f 0
nc 1
dl 0
loc 26
rs 8.8571
nop 2
1
/* jshint -W101, -W098 */
2
/* global window */
3
var _ = require('lodash');
4
var blocktrail = require('../');
5
var assert = require('assert');
6
var crypto = require('crypto');
7
var async = require('async');
8
var bitcoin = require('bitcoinjs-lib');
9
var bip39 = require("bip39");
10
11
/**
12
 * @type APIClient
13
 */
14
var client = blocktrail.BlocktrailSDK({
15
    apiKey : process.env.BLOCKTRAIL_SDK_APIKEY || window.BLOCKTRAIL_SDK_APIKEY || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APIKEY",
16
    apiSecret : process.env.BLOCKTRAIL_SDK_APISECRET || window.BLOCKTRAIL_SDK_APISECRET || "EXAMPLE_BLOCKTRAIL_SDK_NODEJS_APISECRET",
17
    testnet : true
18
});
19
20
var TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC = "give pause forget seed dance crawl situate hole keen",
21
    TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC = "give pause forget seed dance crawl situate hole give",
22
    TRANSACTION_TEST_WALLET_PASSWORD = "password";
23
24 View Code Duplication
var _createTestWallet = function(identifier, passphrase, primaryMnemonic, backupMnemonic, cb) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
25
    var keyIndex = 9999;
26
    var network = client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin;
27
28
    var primarySeed = bip39.mnemonicToSeed(primaryMnemonic, passphrase);
29
    var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, network);
30
31
    var backupSeed = bip39.mnemonicToSeed(backupMnemonic, "");
32
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(backupSeed, network);
33
    var backupPublicKey = backupPrivateKey.neutered();
34
35
    var checksum = primaryPrivateKey.getAddress();
36
    var primaryPublicKey = primaryPrivateKey.deriveHardened(keyIndex).neutered();
37
38
    client.storeNewWalletV1(
39
        identifier,
40
        [primaryPublicKey.toBase58(), "M/" + keyIndex + "'"],
41
        [backupPublicKey.toBase58(), "M"],
42
        primaryMnemonic,
43
        checksum,
44
        keyIndex,
45
        function(err, result) {
46
            if (err) {
47
                return cb(err);
48
            }
49
50
            var blocktrailPublicKeys = _.mapValues(result.blocktrail_public_keys, function(blocktrailPublicKey) {
51
                return bitcoin.HDNode.fromBase58(blocktrailPublicKey[0], network);
52
            });
53
54
            var wallet = new blocktrail.Wallet(
55
                client,
56
                identifier,
57
                blocktrail.Wallet.WALLET_VERSION_V1,
58
                primaryMnemonic,
59
                null,
60
                null,
61
                {keyIndex: primaryPublicKey},
62
                backupPublicKey,
63
                blocktrailPublicKeys,
64
                keyIndex,
65
                0,
66
                false,
67
                client.testnet,
68
                checksum
69
            );
70
71
            wallet.unlock({
72
                passphrase: passphrase
73
            }, function(err) {
74
                cb(err, wallet);
75
            });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
76
        }
77
    );
78
};
79
80
var createDiscoveryTestWallet = function(identifier, passphrase, cb) {
81
    var primaryMnemonic = "give pause forget seed dance crawl situate hole kingdom";
82
    var backupMnemonic = "give pause forget seed dance crawl situate hole course";
83
84
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, cb);
85
};
86
87
var createTransactionTestWallet = function(identifier, cb) {
88
    return _createTestWallet(identifier, TRANSACTION_TEST_WALLET_PASSWORD, TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_BACKUP_MNEMONIC, cb);
89
};
90
91
var createRecoveryTestWallet = function(identifier, passphrase, cb) {
92
    var primaryMnemonic = "give pause forget seed dance crawl situate hole join";
93
    var backupMnemonic = "give pause forget seed dance crawl situate hole crater";
94
95
    return _createTestWallet(identifier, passphrase, primaryMnemonic, backupMnemonic, cb);
96
};
97
98
/**
99
 * Test operations on v2 and v3 wallets.
100
 * Also tests the default, encouraging to look at this test if it changes again.
101
 */
102
[
103
  blocktrail.Wallet.WALLET_VERSION_V2,
104
  blocktrail.Wallet.WALLET_VERSION_V3,
105
  null /* test our assumed default version */
106
].map(function(walletVersion) {
107
    var assumedDefault = blocktrail.Wallet.WALLET_VERSION_V3;
108
    describe('test new blank wallet, ' + walletVersion, function() {
109
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
110
        var wallet;
111
112
        after(function(cb) {
113
            if (wallet) {
114
                wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
115
                    cb();
116
                });
117
            } else {
118
                cb();
119
            }
120
        });
121
122
        it("shouldn't already exist", function(cb) {
123
            client.initWallet({
124
                identifier: myIdentifier,
125
                readOnly: true
126
            }, function(err, wallet) {
127
                assert.ok(err);
128
                assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
129
130
                cb();
131
            });
132
        });
133
134
        it("should be created", function(cb) {
135
            var progress = [];
136
            var cnf = {
137
                identifier: myIdentifier,
138
                passphrase: "password",
139
                keyIndex: 9999
140
            };
141
142
            var expectedVersion = assumedDefault;
143
            if (walletVersion !== null) {
144
                cnf.walletVersion = walletVersion;
145
                expectedVersion = walletVersion;
146
            }
147
148
            client.createNewWallet(cnf, function(err, _wallet, backupInfo) {
0 ignored issues
show
Unused Code introduced by
The parameter backupInfo is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
149
                assert.ifError(err);
150
                assert.ok(_wallet);
151
152
                wallet = _wallet;
153
                assert.equal(wallet.walletVersion, expectedVersion);
154
                assert.equal(wallet.identifier, myIdentifier);
155
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
156
157
                assert.deepEqual(progress, [
158
                    blocktrail.CREATE_WALLET_PROGRESS_START,
159
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_SECRET,
160
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_PRIMARY,
161
                    blocktrail.CREATE_WALLET_PROGRESS_ENCRYPT_RECOVERY,
162
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
163
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
164
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
165
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
166
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
167
                ]);
168
169
                cb();
170
            })
171
            .progress(function(p) { progress.push(p); });
172
        });
173
174
        it("should lock", function(cb) {
175
            assert(!wallet.locked);
176
            wallet.lock();
177
            assert(wallet.locked);
178
            cb();
179
        });
180
181
        it("should init", function(cb) {
182
            client.initWallet({
183
                identifier: myIdentifier,
184
                readOnly: true
185
            }, function(err, _wallet) {
186
                assert.ifError(err);
187
                assert.ok(_wallet);
188
189
                wallet = _wallet;
190
191
                cb();
192
            });
193
        });
194
195
        it("should have a 0 balance", function(cb) {
196
            wallet.getBalance(function(err, confirmed, unconfirmed) {
197
                assert.ifError(err);
198
                assert.equal(confirmed, 0);
199
                assert.equal(unconfirmed, 0);
200
201
                cb();
202
            });
203
        });
204
205
        it("shouldn't be able to pay when locked", function(cb) {
206
            wallet.pay({
207
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
208
            }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
209
                assert.ok(!!err && err.message.match(/unlocked/));
210
                assert.ok(err instanceof blocktrail.WalletLockedError);
211
212
                cb();
213
            });
214
        });
215
216
        it("shouldn't be able to upgrade when locked", function(cb) {
217
            wallet.upgradeKeyIndex(10000, function(err) {
218
                assert.ok(!!err && err.message.match(/unlocked/));
219
                assert.ok(err instanceof blocktrail.WalletLockedError);
220
221
                cb();
222
            });
223
        });
224
225
        it("should unlock", function(cb) {
226
            wallet.unlock({password: "password"}, function(err) {
227
                assert.ifError(err);
228
229
                cb();
230
            });
231
        });
232
233
        it("should be able to unlock with secret", function(cb) {
234
            var secret = wallet.secret;
235
236
            wallet.lock();
237
            wallet.unlock({secret: secret}, function(err) {
238
                assert.ifError(err);
239
                cb();
240
            });
241
        });
242
243
        it("shouldn't be able to pay when unlocked (because of no balance)", function(cb) {
244
            wallet.pay({
245
                "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
246
            }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
247
                assert.ok(!!err && err.message.match(/balance/));
248
249
                cb();
250
            });
251
        });
252
253
        it("should be able to upgrade when unlocked", function(cb) {
254
            wallet.upgradeKeyIndex(10000, function(err) {
255
                assert.ifError(err);
256
257
                cb();
258
            });
259
        });
260
261
        it("should be able to password change", function(cb) {
262
            wallet.passwordChange("password2", function(err) {
263
                assert.ifError(err);
264
265
                client.initWallet({
266
                    identifier: myIdentifier,
267
                    password: "password2"
268
                }, function(err, _wallet) {
269
                    assert.ifError(err);
270
                    assert.ok(_wallet);
271
272
                    wallet = _wallet;
273
274
                    cb();
275
                });
276
            });
277
        });
278
    });
279
});
280
281
/**
282
 * Test operations on v2 and v3 wallets.
283
 */
284
[
285
    blocktrail.Wallet.WALLET_VERSION_V1,
286
    blocktrail.Wallet.WALLET_VERSION_V2,
287
    blocktrail.Wallet.WALLET_VERSION_V3
288
].map(function(walletVersion) {
289
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
290
291
    describe('test input errors, ' + walletVersion, function() {
292
        it("shouldn't allow primaryPrivateKey in creation", function(cb) {
293
            var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
294
            var primaryPrivateKey = bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet);
295
296
            client.createNewWallet({
297
                identifier: myIdentifier,
298
                passphrase: "password",
299
                primaryPrivateKey: primaryPrivateKey,
300
                walletVersion: walletVersion,
301
                keyIndex: 9999
302
            }, function(err, wallet) {
0 ignored issues
show
Unused Code introduced by
The parameter wallet is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
303
                assert.ok(!!err, "should error");
304
305
                cb();
306
            });
307
        });
308
309
        it("shouldn't allow unlocking with primaryPrivateKey", function(cb) {
310
            client.createNewWallet({
311
                identifier: "unittest-transaction-inputerr-" + walletVersion,
312
                primarySeed: primarySeed,
313
                walletVersion: walletVersion,
314
                keyIndex: 9999
315
            }).then(function(r) {
316
                var wallet = r[0];
317
                wallet.lock();
318
                return wallet;
319
            }, function(err) {
320
                assert.ok(err.message.match(/already exists/));
321
322
                return client.initWallet({
323
                    identifier: "unittest-transaction-inputerr-" + walletVersion,
324
                    readOnly: true
325
                });
326
            }).then(function(wallet) {
327
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
328
329
                return wallet.unlock({primaryPrivateKey: bitcoin.HDNode.fromSeedBuffer(primarySeed, bitcoin.networks.testnet)})
330
                    .then(function() {
331
                        return;
0 ignored issues
show
Unused Code introduced by
This return has no effect and can be removed.
Loading history...
332
                    }, function(err) {
333
                        return err;
334
                    });
335
            })
336
                .then(function(err) {
337
                    assert.ok(!!err, "should error");
338
                    cb();
339
                })
340
                .done();
341
        });
342
    });
343
});
344
345
/**
346
 * Test upgrade to V3 from V1 and V2
347
 */
348
[
349
    blocktrail.Wallet.WALLET_VERSION_V1,
350
    blocktrail.Wallet.WALLET_VERSION_V2
351
].map(function(walletVersion) {
352
    describe("upgrade to V3 from " + walletVersion, function() {
353
        var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
354
        var passphrase = "password";
355
        var wallet;
356
357
        after(function(cb) {
358
            if (wallet) {
359
                wallet.deleteWallet(true, function(err, result) {
360
                    console.log(err, result);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
361
                    cb();
362
                });
363
            } else {
364
                cb();
365
            }
366
        });
367
368
        it("can upgrade", function() {
369
            var addr;
370
            return client.createNewWallet({
371
                identifier: myIdentifier,
372
                passphrase: passphrase,
373
                walletVersion: walletVersion,
374
                keyIndex: 9999
375
            })
376
                .then(function(r) {
377
                    return r[0];
378
                })
379
                .then(function(_wallet) {
380
                    wallet = _wallet;
381
                    addr = wallet.getAddressByPath("M/9999'/0/0");
382
383
                    return wallet;
384
                })
385
                .then(function(wallet) {
386
                    var progress = [];
387
388
                    return wallet.upgradeToV3(passphrase)
389
                        .progress(function(p) {
390
                            progress.push(p);
391
                        })
392
                        .then(function() {
393
                            assert(progress.length);
394
                            return wallet;
395
                        });
396
                })
397
                .then(function(wallet) {
398
                    assert.equal(addr, wallet.getAddressByPath("M/9999'/0/0"));
399
                });
400
        });
401
402
        it("can unlock with secret", function() {
403
            var secret = wallet.secret;
404
            wallet.lock();
405
            return wallet.unlock({secret: secret});
406
        });
407
408
        it("can init after upgrade", function() {
409
            return client.initWallet({
410
                identifier: myIdentifier,
411
                passphrase: passphrase,
412
                keyIndex: 9999
413
            });
414
        });
415
    });
416
});
417
418
describe('test new blank wallet, v1', function() {
419
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
420
    var wallet;
421
422
    after(function(cb) {
423
        if (wallet) {
424
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
425
                cb();
426
            });
427
        } else {
428
            cb();
429
        }
430
    });
431
432
    it("shouldn't already exist", function(cb) {
433
        client.initWallet({
434
            identifier: myIdentifier,
435
            readOnly: true
436
        }, function(err, wallet) {
437
            assert.ok(err);
438
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
439
440
            cb();
441
        });
442
    });
443
444
    it("should be created", function(cb) {
445
        var progress = [];
446
447
        client.createNewWallet({
448
                identifier: myIdentifier,
449
                passphrase: "password",
450
                keyIndex: 9999,
451
                walletVersion: blocktrail.Wallet.WALLET_VERSION_V1
452
            }, function(err, _wallet) {
453
                assert.ifError(err);
454
                assert.ok(_wallet);
455
456
                wallet = _wallet;
457
458
                assert.equal(wallet.identifier, myIdentifier);
459
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
460
461
                assert.deepEqual(progress, [
462
                    blocktrail.CREATE_WALLET_PROGRESS_START,
463
                    blocktrail.CREATE_WALLET_PROGRESS_PRIMARY,
464
                    blocktrail.CREATE_WALLET_PROGRESS_BACKUP,
465
                    blocktrail.CREATE_WALLET_PROGRESS_SUBMIT,
466
                    blocktrail.CREATE_WALLET_PROGRESS_INIT,
467
                    blocktrail.CREATE_WALLET_PROGRESS_DONE
468
                ]);
469
470
                cb();
471
            }
472
        ).progress(function(p) { progress.push(p); });
473
    });
474
475
    it("should lock", function(cb) {
476
        assert(!wallet.locked);
477
        wallet.lock();
478
        assert(wallet.locked);
479
        cb();
480
    });
481
482
    it("should init", function(cb) {
483
        client.initWallet({
484
            identifier: myIdentifier,
485
            readOnly: true
486
        }, function(err, _wallet) {
487
            assert.ifError(err);
488
            assert.ok(_wallet);
489
            assert.equal(wallet.walletVersion, 'v1');
490
491
            wallet = _wallet;
492
493
            cb();
494
        });
495
    });
496
497
    it("should have a 0 balance", function(cb) {
498
        wallet.getBalance(function(err, confirmed, unconfirmed) {
499
            assert.ifError(err);
500
            assert.equal(confirmed, 0);
501
            assert.equal(unconfirmed, 0);
502
503
            cb();
504
        });
505
    });
506
507
    it("should unlock", function(cb) {
508
        wallet.unlock({password: "password"}, function(err) {
509
            assert.ifError(err);
510
511
            cb();
512
        });
513
    });
514
515
    it("shouldn't be able to password change", function(cb) {
516
        wallet.passwordChange("password2", function(err) {
517
            assert.ok(!!err && err.message.match(/version does not support/));
518
519
            cb();
520
        });
521
    });
522
});
523
524
describe('test new blank wallet, old syntax', function() {
525
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
526
    var wallet;
527
528
    after(function(cb) {
529
        if (wallet) {
530
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
531
                cb();
532
            });
533
        } else {
534
            cb();
535
        }
536
    });
537
538
    it("shouldn't already exist", function(cb) {
539
        client.initWallet(myIdentifier, "password", function(err, wallet) {
540
            assert.ok(err);
541
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
542
543
            cb();
544
        });
545
    });
546
547
    it("should be created", function(cb) {
548
        client.createNewWallet(myIdentifier, "password", 9999, function(err, _wallet) {
549
            assert.ifError(err);
550
            assert.ok(_wallet);
551
552
            wallet = _wallet;
553
554
            assert.equal(wallet.identifier, myIdentifier);
555
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
556
            cb();
557
        });
558
    });
559
560
    it("should have a 0 balance", function(cb) {
561
        wallet.getBalance(function(err, confirmed, unconfirmed) {
562
            assert.ifError(err);
563
            assert.equal(confirmed, 0);
564
            assert.equal(unconfirmed, 0);
565
566
            cb();
567
        });
568
    });
569
570
    it("shouldn't be able to pay", function(cb) {
571
        wallet.pay({
572
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
573
        }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
574
            assert.ok(!!err);
575
576
            cb();
577
        });
578
    });
579
});
580
581
describe('test new wallet, without mnemonics', function() {
582
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
583
    var wallet;
584
585
    var primarySeed = bip39.mnemonicToSeed(bip39.generateMnemonic(512), "password");
586
    var backupPrivateKey = bitcoin.HDNode.fromSeedBuffer(bip39.mnemonicToSeed(bip39.generateMnemonic(512), ""), bitcoin.networks.testnet);
587
    var backupPublicKey = backupPrivateKey.neutered();
588
589
    after(function(cb) {
590
        if (wallet) {
591
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
592
                cb();
593
            });
594
        } else {
595
            cb();
596
        }
597
    });
598
599
    it("shouldn't already exist", function(cb) {
600
        client.initWallet({
601
            identifier: myIdentifier
602
        }, function(err, wallet) {
603
            assert.ok(err);
604
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
605
606
            cb();
607
        });
608
    });
609
610
    it("should be created", function(cb) {
611
        client.createNewWallet({
612
                identifier: myIdentifier,
613
                primarySeed: primarySeed,
614
                backupPublicKey: backupPublicKey,
615
                keyIndex: 9999
616
            }, function(err, _wallet) {
617
                assert.ifError(err);
618
                assert.ok(_wallet);
619
620
                wallet = _wallet;
621
622
                assert.equal(wallet.identifier, myIdentifier);
623
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
624
                cb();
625
            }
626
        );
627
    });
628
629
    it("should be initializable", function(cb) {
630
        client.initWallet({
631
                identifier: myIdentifier,
632
                primarySeed: primarySeed,
633
                keyIndex: 9999
634
            }, function(err, _wallet) {
635
                assert.ifError(err);
636
                assert.ok(_wallet);
637
638
                wallet = _wallet;
639
640
                cb();
641
            }
642
        );
643
    });
644
645
    it("should have a 0 balance", function(cb) {
646
        wallet.getBalance(function(err, confirmed, unconfirmed) {
647
            assert.ifError(err);
648
            assert.equal(confirmed, 0);
649
            assert.equal(unconfirmed, 0);
650
651
            cb();
652
        });
653
    });
654
655
    it("shouldn't be able to pay", function(cb) {
656
        wallet.pay({
657
            "2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy": blocktrail.toSatoshi(0.001)
658
        }, function(err, txHash) {
0 ignored issues
show
Unused Code introduced by
The parameter txHash is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
659
            assert.ok(!!err);
660
661
            cb();
662
        });
663
    });
664
});
665
666
describe('test wallet, do transaction', function() {
667
    var wallet;
668
669
    it("should exists", function(cb) {
670
        client.initWallet({
671
            identifier: "unittest-transaction",
672
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
673
        }, function(err, _wallet) {
674
            assert.ifError(err);
675
            assert.ok(_wallet);
676
            wallet = _wallet;
677
678
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
679
            assert.equal(wallet.identifier, "unittest-transaction");
680
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
681
            cb();
682
        });
683
    });
684
685
    it("should have the expected addresses", function(cb) {
686
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
687
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
688
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
689
690
        cb();
691
    });
692
693
    it("should have a balance", function(cb) {
694
        this.timeout(0);
695
696
        wallet.getBalance(function(err, confirmed, unconfirmed) {
697
            assert.ok(confirmed + unconfirmed > 0);
698
            assert.ok(confirmed > 0);
699
700
            cb();
701
        });
702
    });
703
704
    it("should return errors when expected", function(cb) {
705
        async.parallel([
706
            function(cb) {
707
                wallet.pay({"": blocktrail.toSatoshi(0.001)}, function(err) {
708
                    assert.ok(!!err);
709
                    assert.equal(err.message, "Invalid address [] (Invalid checksum)");
710
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
711
712
                    cb();
713
                });
714
            },
715
            function(cb) {
716
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA": blocktrail.toSatoshi(0.001)}, function(err) {
717
                    assert.ok(!!err);
718
                    assert.equal(err.message, "Invalid address [2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHA] (Invalid checksum)");
719
                    assert.ok(err instanceof blocktrail.InvalidAddressError);
720
721
                    cb();
722
                });
723
            },
724
            function(cb) {
725
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1}, function(err) {
726
                    assert.ok(!!err);
727
                    assert.equal(err.message, "Values should be more than dust (" + blocktrail.DUST + ")");
728
                    assert.ok(err instanceof blocktrail.WalletSendError);
729
730
                    cb();
731
                });
732
            },
733
            function(cb) {
734
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 0}, function(err) {
735
                    assert.ok(!!err);
736
                    assert.equal(err.message, "Values should be non zero");
737
                    assert.ok(err instanceof blocktrail.WalletSendError);
738
739
                    cb();
740
                });
741
            },
742
            function(cb) {
743
                wallet.pay({"2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD": 1.1}, function(err) {
744
                    assert.ok(!!err);
745
                    assert.equal(err.message, "Values should be in Satoshis");
746
                    assert.ok(err instanceof blocktrail.WalletSendError);
747
748
                    cb();
749
                });
750
            }
751
        ], cb);
752
    });
753
754
    it("should be able to build a transaction paying a bech32 address", function(cb) {
755
        var address = "tb1qn08f8x0eamw66enrt497zu0v3u2danzey6asqs";
756
        var wp = "00149bce9399f9eeddad66635d4be171ec8f14decc59";
757
        var pay = {};
758
        pay[address] = blocktrail.toSatoshi(0.001);
759
760
        wallet.buildTransaction(pay, null, false, false, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
761
            assert.ifError(err);
762
            assert.ok(tx);
763
            assert.ok(tx.toHex());
764
            assert.equal(wp, tx.outs[0].script.toString('hex'));
765
            cb();
766
        });
767
    });
768
769
    it("change should be randomized when building a transaction", function(cb) {
770
        wallet.getNewAddress(function(err, address, path) {
771
            assert.ifError(err);
772
            assert.ok(path.indexOf("M/9999'/0/") === 0);
773
            assert.ok(bitcoin.address.fromBase58Check(address));
774
775
            var pay = {};
776
            pay[address] = blocktrail.toSatoshi(0.001);
777
778
            var changeIdxs = [];
779
            var tryX = 10;
780
781
            async.whilst(
782
                function() { return tryX-- > 0 && _.uniq(changeIdxs).length < 2; },
783
                function(cb) {
784
                    wallet.buildTransaction(pay, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
785
                        assert.ifError(err);
786
787
                        tx.outs.forEach(function(output, idx) {
788
                            var addr = bitcoin.address.fromOutputScript(output.script, client.testnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin);
789
790
                            if (addr !== address) {
791
                                changeIdxs.push(idx);
792
                            }
793
                        });
794
795
                        cb();
796
                    });
797
                },
798
                function() {
799
                    assert(_.uniq(changeIdxs).length > 1);
800
801
                    cb();
802
                }
803
            );
804
        });
805
806
        it("should be able to build a transaction", function(cb) {
0 ignored issues
show
Unused Code introduced by
The parameter cb is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
807
            wallet.getNewAddress(function(err, address, path) {
808
                assert.ifError(err);
809
                assert.ok(path.indexOf("M/9999'/0/") === 0);
810
                assert.ok(bitcoin.address.fromBase58Check(address));
811
812
                var pay = {};
813
                pay[address] = blocktrail.toSatoshi(0.001);
814
815
                wallet.buildTransaction(pay, function(err, tx, utxos) {
0 ignored issues
show
Unused Code introduced by
The parameter utxos is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
816
                    assert.ifError(err);
817
                    assert.ok(tx);
818
                    assert.ok(tx.toHex());
819
                });
820
            });
821
        });
822
    });
823
824
    it("should be able to do a payment", function(cb) {
825
        wallet.getNewAddress(function(err, address, path) {
826
            assert.ifError(err);
827
            assert.ok(path.indexOf("M/9999'/", wallet.chain, "/") === 0);
828
            assert.ok(bitcoin.address.fromBase58Check(address));
829
830
            var pay = {};
831
            pay[address] = blocktrail.toSatoshi(0.001);
832
833
            var progress = [];
834
835
            wallet.pay(pay, function(err, txHash) {
836
                assert.ifError(err);
837
                assert.ok(txHash);
838
839
                // change address doesn't always happen ...
840
                if (progress.indexOf(blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS) === -1) {
841
                    progress.splice(2, 0, blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS);
842
                }
843
844
                assert.deepEqual(progress, [
845
                    blocktrail.Wallet.PAY_PROGRESS_START,
846
                    blocktrail.Wallet.PAY_PROGRESS_COIN_SELECTION,
847
                    blocktrail.Wallet.PAY_PROGRESS_CHANGE_ADDRESS,
848
                    blocktrail.Wallet.PAY_PROGRESS_SIGN,
849
                    blocktrail.Wallet.PAY_PROGRESS_SEND,
850
                    blocktrail.Wallet.PAY_PROGRESS_DONE
851
                ]);
852
853
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
854
                setTimeout(function() {
855
                    client.transaction(txHash, function(err, tx) {
856
                        assert.ifError(err);
857
                        assert.ok(tx);
858
859
                        cb();
860
                    });
861
                }, 200);
862
            }).progress(function(_progress) {
863
                progress.push(_progress);
864
            });
865
        });
866
    });
867
});
868
869
describe('test wallet with segwit chain', function() {
870
    var wallet;
871
872
    it("should exist and be setup", function(cb) {
873
        client.initWallet({
874
            identifier: "unittest-transaction",
875
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
876
        }, function(err, _wallet) {
877
            assert.ifError(err);
878
            assert.ok(_wallet);
879
            assert.equal(_wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
880
            assert.equal(_wallet.identifier, "unittest-transaction");
881
            assert.equal(_wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
882
883
            if (_wallet.isSegwit()) {
884
                assert.equal(blocktrail.Wallet.CHAIN_BTC_SEGWIT, _wallet.chain);
885
            } else {
886
                assert.equal(blocktrail.Wallet.CHAIN_BTC_DEFAULT, _wallet.chain);
887
            }
888
889
            wallet = _wallet;
890
            cb();
891
        });
892
    });
893
894
    it("getNewAddress produces P2SH addresses", function(cb) {
895
        wallet.getNewAddress(function(err, address, path) {
896
            assert.ifError(err);
897
            if (wallet.isSegwit()) {
898
                assert.ok(path.indexOf("M/9999'/2/") === 0);
899
            } else {
900
                assert.ok(path.indexOf("M/9999'/0/") === 0);
901
            }
902
903
            assert.ok(bitcoin.address.fromBase58Check(address));
904
905
            cb();
906
        });
907
    });
908
909
    it("getWalletScriptByPath produces P2SH addresses, and returns witnessScript", function(cb) {
910
        var eAddress = "2N3j4Vx3D9LPumjtRbRe2RJpwVocvCCkHKh";
911
912
        assert.equal(wallet.getAddressByPath("M/9999'/2/0"), eAddress);
913
914
        var walletScript = wallet.getWalletScriptByPath("M/9999'/2/0");
915
        assert.equal(walletScript.address, eAddress);
916
        assert.ok(walletScript.witnessScript);
917
        assert.ok(walletScript.redeemScript);
918
        cb();
919
    });
920
});
921
922
describe('test wallet, do transaction, segwit spend', function() {
923
    var wallets = [];
924
    after(function(cb) {
925
        if (wallets.length > 0) {
926
            wallets.map(function(wallet) {
927
                wallet.deleteWallet(true);
928
            });
929
        }
930
        cb();
931
    });
932
933
    var unitTestWallet;
934
    var identifier = crypto.randomBytes(12).toString('hex');
935
    var segwitWallet;
936
    var receiveAddr;
937
    var receiveBackAddr;
938
    it("should setup the funding wallet", function(cb) {
939
        client.initWallet({
940
            identifier: "unittest-transaction",
941
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
942
        }, function(err, _wallet) {
943
            assert.ifError(err);
944
            assert.ok(_wallet);
945
946
            _wallet.getNewAddress(function(err, address, path) {
947
                assert.ifError(err);
948
                assert.ok(address);
949
                assert.ok(path);
950
951
                unitTestWallet = _wallet;
952
                receiveBackAddr = address;
953
                cb();
954
            });
955
        });
956
    });
957
958
    it("should make the receiving segwit wallet ", function(cb) {
959
        createTransactionTestWallet(identifier, function(err, newWallet) {
960
            wallets.push(newWallet);
961
            assert.ifError(err);
962
            newWallet.getNewAddress(function(err, address, path) {
963
                assert.ifError(err);
964
                assert.ok(bitcoin.address.fromBase58Check(address));
965
966
                if (newWallet.isSegwit()) {
967
                    assert.ok(path.indexOf("M/9999'/2/") === 0);
968
                } else {
969
                    assert.ok(path.indexOf("M/9999'/0/") === 0);
970
                }
971
972
                var checkScript = newWallet.getWalletScriptByPath(path);
973
                assert.ok(checkScript.address = address);
974
                assert.ok(checkScript.redeemScript instanceof Buffer);
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
975
                if (newWallet.isSegwit()) {
976
                    assert.ok(checkScript.witnessScript instanceof Buffer);
977
                }
978
979
980
                segwitWallet = newWallet;
981
                receiveAddr = address;
982
                cb();
983
            });
984
        });
985
    });
986
987
    var paymentHash;
988
    it("should receive funds from unitTestWallet", function(cb) {
989
        var pay = {};
990
        pay[receiveAddr] = 30000;
991
        unitTestWallet.pay(pay, null, true, function(err, txid) {
992
            assert.ifError(err);
993
            assert.ok(txid);
994
            paymentHash = txid;
0 ignored issues
show
Unused Code introduced by
The variable paymentHash seems to be never used. Consider removing it.
Loading history...
995
            cb();
996
        });
997
    });
998
999
    it("should return to unitTestWallet", function(cb) {
1000
        var pay = {};
1001
        pay[receiveBackAddr] = 20000;
1002
        segwitWallet.pay(pay, null, true, function(err, txid) {
1003
            assert.ifError(err);
1004
            assert.ok(txid);
1005
1006
            client.transaction(txid, function(err, tx) {
1007
                assert.ifError(err);
1008
                assert.ok(tx);
1009
                cb();
1010
            });
1011
        });
1012
    });
1013
});
1014
describe('test wallet, do transaction, without mnemonics', function() {
1015
    var wallet;
1016
1017
    var primarySeed = bip39.mnemonicToSeed(TRANSACTION_TEST_WALLET_PRIMARY_MNEMONIC, TRANSACTION_TEST_WALLET_PASSWORD);
1018
1019
    it("should exists", function(cb) {
1020
        client.initWallet({
1021
                identifier: "unittest-transaction",
1022
                primarySeed: primarySeed,
1023
                primaryMnemonic: false // explicitly set false because we're reusing unittest-transaction which has a mnemonic stored
1024
            }, function(err, _wallet) {
1025
                assert.ifError(err);
1026
                assert.ok(_wallet);
1027
1028
                wallet = _wallet;
1029
1030
                assert.equal(wallet.identifier, "unittest-transaction");
1031
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1032
                cb();
1033
            }
1034
        );
1035
    });
1036
1037
    it("should have the expected addresses", function(cb) {
1038
        assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2N65RcfKHiKQcPGZAA2QVeqitJvAQ8HroHD");
1039
        assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2MynrezSyqCq1x5dMPtRDupTPA4sfVrNBKq");
1040
        assert.equal(wallet.getAddressByPath("M/9999'/0/44"), "2N5eqrZE7LcfRyCWqpeh1T1YpMdgrq8HWzh");
1041
1042
        cb();
1043
    });
1044
1045
    it("should have a balance", function(cb) {
1046
        this.timeout(0);
1047
1048
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1049
            assert.ok(confirmed + unconfirmed > 0);
1050
            assert.ok(confirmed > 0);
1051
1052
            cb();
1053
        });
1054
    });
1055
1056
    it("should be able to do a payment", function(cb) {
1057
        wallet.getNewAddress(function(err, address, path) {
1058
            assert.ifError(err);
1059
            assert.ok(path.indexOf("M/9999'/0/") === 0);
1060
            assert.ok(bitcoin.address.fromBase58Check(address));
1061
1062
            var pay = {};
1063
            pay[address] = blocktrail.toSatoshi(0.001);
1064
1065
            wallet.pay(pay, function(err, txHash) {
1066
                assert.ifError(err);
1067
                assert.ok(txHash);
1068
1069
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1070
                setTimeout(function() {
1071
                    client.transaction(txHash, function(err, tx) {
1072
                        assert.ifError(err);
1073
                        assert.ok(tx);
1074
1075
                        cb();
1076
                    });
1077
                }, 200);
1078
            });
1079
        });
1080
    });
1081
});
1082
1083
describe('test wallet, do opreturn transaction', function() {
1084
    var wallet;
1085
1086
    it("should exists", function(cb) {
1087
        client.initWallet({
1088
            identifier: "unittest-transaction",
1089
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1090
        }, function(err, _wallet) {
1091
            assert.ifError(err);
1092
            assert.ok(_wallet);
1093
1094
            wallet = _wallet;
1095
1096
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1097
            assert.equal(wallet.identifier, "unittest-transaction");
1098
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1099
            cb();
1100
        });
1101
    });
1102
1103
    it("should be able to do a payment with opreturn output", function(cb) {
1104
        wallet.getNewAddress(function(err, address, path) {
0 ignored issues
show
Unused Code introduced by
The parameter path is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1105
            assert.ifError(err);
1106
1107
            var pay = {};
1108
            pay[address] = blocktrail.toSatoshi(0.001);
1109
            pay[blocktrail.Wallet.OP_RETURN] = "BLOCKTRAILTESTDATA";
1110
1111
            wallet.pay(pay, function(err, txHash) {
1112
                assert.ifError(err);
1113
                assert.ok(txHash);
1114
1115
1116
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1117
                setTimeout(function() {
1118
                    client.transaction(txHash, function(err, tx) {
1119
                        assert.ifError(err);
1120
                        assert.ok(tx);
1121
1122
                        var hasOpreturn;
1123
                        tx.outputs.forEach(function(output) {
1124
                            if (output.type === 'op_return') {
1125
                                hasOpreturn = true;
1126
1127
                                assert.equal(output.script_hex, "6a12424c4f434b545241494c5445535444415441");
1128
                            }
1129
                        });
1130
                        assert.ok(hasOpreturn);
1131
1132
                        cb();
1133
                    });
1134
                }, 200);
1135
            });
1136
        });
1137
    });
1138
});
1139
1140
describe('test wallet, do forcefee transaction', function() {
1141
    var wallet;
1142
1143
    it("should exists", function(cb) {
1144
        client.initWallet({
1145
            identifier: "unittest-transaction",
1146
            passphrase: TRANSACTION_TEST_WALLET_PASSWORD
1147
        }, function(err, _wallet) {
1148
            assert.ifError(err);
1149
            assert.ok(_wallet);
1150
1151
            wallet = _wallet;
1152
1153
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1154
            assert.equal(wallet.identifier, "unittest-transaction");
1155
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1156
            cb();
1157
        });
1158
    });
1159
1160
    it("should be able to do a payment with forced fee", function(cb) {
1161
        wallet.getNewAddress(function(err, address, path) {
0 ignored issues
show
Unused Code introduced by
The parameter path is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1162
            assert.ifError(err);
1163
1164
            var pay = {};
1165
            pay[address] = blocktrail.toSatoshi(0.01);
1166
            var forceFee = blocktrail.toSatoshi(0.00054321);
1167
1168
            wallet.pay(pay, null, false, true, blocktrail.Wallet.FEE_STRATEGY_FORCE_FEE, null, {
1169
                forcefee: forceFee,
1170
                checkFee: false
1171
            }, function(err, txHash) {
1172
                assert.ifError(err);
1173
                assert.ok(txHash);
1174
1175
                // 200ms timeout, for w/e this is neccesary now ... @TODO: figure out why ...
1176
                setTimeout(function() {
1177
                    client.transaction(txHash, function(err, tx) {
1178
                        assert.ifError(err);
1179
                        // this could very occasionally fail if change < DUST because then it's added to fee, so adjusted check for that
1180
                        assert.ok(tx['total_fee'] >= forceFee && tx['total_fee'] <= forceFee + blocktrail.DUST,
1181
                            "fee [" + tx['total_fee'] + "] should be equal to forced fee [" +  forceFee + "] for tx [" + txHash + "]");
1182
1183
                        cb();
1184
                    });
1185
                }, 200);
1186
            });
1187
        });
1188
    });
1189
});
1190
1191
describe('test wallet discovery and upgrade key index', function() {
1192
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1193
    var wallet;
1194
1195
    after(function(cb) {
1196
        if (wallet) {
1197
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1198
                cb();
1199
            });
1200
        } else {
1201
            cb();
1202
        }
1203
    });
1204
1205
    it("should be created", function(cb) {
1206
        createDiscoveryTestWallet(myIdentifier, "password", function(err, _wallet) {
1207
            assert.ifError(err);
1208
            assert.ok(_wallet);
1209
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1210
            wallet = _wallet;
1211
1212
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1213
            assert.equal(wallet.identifier, myIdentifier);
1214
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1215
1216
            cb();
1217
        });
1218
    });
1219
1220
    it("should have the expected addresses", function(cb) {
1221
        async.series([
1222
            function(cb) {
1223
                wallet.getNewAddress(function(err, address, path) {
1224
                    assert.ifError(err);
1225
                    assert.equal(path, "M/9999'/0/0");
1226
                    assert.equal(address, "2Mtfn5S9tVWnnHsBQixCLTsCAPFHvfhu6bM");
1227
1228
                    cb();
1229
                });
1230
            },
1231
            function(cb) {
1232
                wallet.getNewAddress(function(err, address, path) {
1233
                    assert.ifError(err);
1234
                    assert.equal(path, "M/9999'/0/1");
1235
                    assert.equal(address, "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1236
1237
                    cb();
1238
                });
1239
            },
1240
            function(cb) {
1241
                assert.equal(wallet.getAddressByPath("M/9999'/0/1"), "2NG49GDkm5qCYvDFi4cxAnkSho8qLbEz6C4");
1242
                assert.equal(wallet.getAddressByPath("M/9999'/0/6"), "2N1kM5xeDaCN9Weog3mbyxjpryNZcirnkB7");
1243
1244
                cb();
1245
            }
1246
        ], cb);
1247
    });
1248
1249
    it("should have a balance after discovery", function(cb) {
1250
        this.timeout(0);
1251
1252
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1253
            assert.ok(confirmed + unconfirmed > 0);
1254
1255
            cb();
1256
        });
1257
    });
1258
1259
    it("should be upgraded and have expected addresses", function(cb) {
1260
        // set upgrade
1261
        wallet.upgradeToKeyIndex = 10000;
1262
        // lock
1263
        wallet.lock();
1264
        // unlock should upgrade
1265
        wallet.unlock({
1266
            passphrase: "password"
1267
        }).then(function() {
1268
            assert.equal(wallet.getBlocktrailPublicKey("M/10000'").toBase58(), "tpubD9m9hziKhYQExWgzMUNXdYMNUtourv96sjTUS9jJKdo3EDJAnCBJooMPm6vGSmkNTNAmVt988dzNfNY12YYzk9E6PkA7JbxYeZBFy4XAaCp");
1269
1270
            assert.equal(wallet.getAddressByPath("M/10000'/0/0"), "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1271
1272
            wallet.getNewAddress(function(err, address, path) {
1273
                assert.ifError(err);
1274
                assert.equal(path, "M/10000'/0/0");
1275
                assert.equal(address, "2N9ZLKXgs12JQKXvLkngn7u9tsYaQ5kXJmk");
1276
1277
                cb();
1278
            });
1279
        });
1280
    });
1281
});
1282
1283
describe('test wallet with bad password', function() {
1284
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1285
    var wallet;
1286
1287
    after(function(cb) {
1288
        if (wallet) {
1289
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1290
                cb();
1291
            });
1292
        } else {
1293
            cb();
1294
        }
1295
    });
1296
1297
    it("should be created", function(cb) {
1298
        createDiscoveryTestWallet(myIdentifier, "badpassword", function(err, _wallet) {
1299
            assert.ifError(err);
1300
            assert.ok(_wallet);
1301
1302
            _wallet.chain = blocktrail.Wallet.CHAIN_BTC_DEFAULT;
1303
            wallet = _wallet;
1304
1305
            assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole kingdom");
1306
            assert.equal(wallet.identifier, myIdentifier);
1307
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1308
1309
            cb();
1310
        });
1311
    });
1312
1313
    it("should have the expected addresses (different from with the correct password)", function(cb) {
1314
        async.series([
1315
            function(cb) {
1316
                wallet.getNewAddress(function(err, address, path) {
1317
                    assert.ifError(err);
1318
                    assert.equal(path, "M/9999'/0/0");
1319
                    assert.equal(address, "2N9SGrV4NKRjdACYvHLPpy2oiPrxTPd44rg");
1320
1321
                    cb();
1322
                });
1323
            },
1324
            function(cb) {
1325
                wallet.getNewAddress(function(err, address, path) {
1326
                    assert.ifError(err);
1327
                    assert.equal(path, "M/9999'/0/1");
1328
                    assert.equal(address, "2NDq3DRy9E3YgHDA3haPJj3FtUS6V93avkf");
1329
1330
                    cb();
1331
                });
1332
            }
1333
        ], cb);
1334
    });
1335
1336
    it("shouldn't have a balance after discovery", function(cb) {
1337
        this.timeout(0);
1338
1339
        wallet.doDiscovery(50, function(err, confirmed, unconfirmed) {
1340
            assert.ok(confirmed + unconfirmed === 0);
1341
1342
            cb();
1343
        });
1344
    });
1345
});
1346
1347
describe('test wallet webhook', function() {
1348
    // this.timeout(0); // disable, can take long
1349
1350
    var myIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1351
    var wallet;
1352
1353
    after(function(cb) {
1354
        if (wallet) {
1355
            wallet.deleteWallet(true, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter err is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1356
                cb();
1357
            });
1358
        } else {
1359
            cb();
1360
        }
1361
    });
1362
1363
    it("shouldn't already exist", function(cb) {
1364
        client.initWallet({
1365
            identifier: myIdentifier,
1366
            passphrase: "password"
1367
        }, function(err, wallet) {
1368
            assert.ok(err);
1369
            assert.ok(!wallet, "wallet with random ID [" + myIdentifier + "] already exists...");
1370
1371
            cb();
1372
        });
1373
    });
1374
1375
    it("should be created", function(cb) {
1376
        client.createNewWallet({
1377
            identifier: myIdentifier,
1378
            passphrase: "password",
1379
            keyIndex: 9999
1380
        }, function(err, _wallet) {
1381
            assert.ifError(err);
1382
            assert.ok(_wallet);
1383
1384
            wallet = _wallet;
1385
1386
            assert.equal(wallet.identifier, myIdentifier);
1387
            assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1388
            cb();
1389
        });
1390
    });
1391
1392
    it("should have a 0 balance", function(cb) {
1393
        wallet.getBalance(function(err, confirmed, unconfirmed) {
1394
            assert.ifError(err);
1395
            assert.equal(confirmed, 0);
1396
            assert.equal(unconfirmed, 0);
1397
1398
            cb();
1399
        });
1400
    });
1401
1402
    it("should be able to create a webhook", function(cb) {
1403
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", function(err, webhook) {
1404
            assert.ifError(err);
1405
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1406
            assert.equal(webhook['identifier'], "WALLET-" + myIdentifier);
1407
1408
            wallet.deleteWebhook(function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1409
                assert.ifError(err);
1410
1411
                cb();
1412
            });
1413
        });
1414
    });
1415
1416
    it("should be able to create a webhook with custom identifier", function(cb) {
1417
        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1418
1419
        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1420
            assert.ifError(err);
1421
            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1422
            assert.equal(webhook['identifier'], myWebhookIdentifier);
1423
1424
            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1425
                assert.ifError(err);
1426
1427
                wallet.getNewAddress(function(err, address1) {
1428
                    assert.ifError(err);
1429
1430
                    wallet.deleteWebhook(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1431
                        assert.ifError(err);
1432
1433
                        var myWebhookIdentifier = "nodejs-sdk-" + crypto.randomBytes(24).toString('hex');
1434
1435
                        wallet.setupWebhook("https://www.blocktrail.com/webhook-test", myWebhookIdentifier, function(err, webhook) {
1436
                            assert.ifError(err);
1437
                            assert.equal(webhook['url'], "https://www.blocktrail.com/webhook-test");
1438
                            assert.equal(webhook['identifier'], myWebhookIdentifier);
1439
1440
                            client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1441
                                assert.ifError(err);
1442
                                assert.ok(_.includes(_.map(result['data'], 'address'), address1));
1443
1444
                                wallet.getNewAddress(function(err, address2) {
1445
                                    assert.ifError(err);
1446
1447
                                    client.getWebhookEvents(myWebhookIdentifier, function(err, result) {
1448
                                        assert.ifError(err);
1449
                                        assert.ok(_.includes(_.map(result['data'], 'address'), address2));
1450
1451
                                        wallet.deleteWallet(function(err, result) {
1452
                                            assert.ifError(err);
1453
                                            assert.ok(result);
1454
1455
                                            client.deleteWebhook(myWebhookIdentifier, function(err, result) {
0 ignored issues
show
Unused Code introduced by
The parameter result is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
1456
                                                assert.ok(err);
1457
1458
                                                cb();
1459
                                            });
1460
                                        });
1461
                                    });
1462
                                });
1463
                            });
1464
                        });
1465
                    });
1466
1467
                });
1468
            });
1469
        });
1470
    });
1471
});
1472
1473
describe('test wallet list transactions and addresses', function() {
1474
    var wallet;
1475
1476
    it("should exists", function(cb) {
1477
        client.initWallet({
1478
            identifier: "unittest-transaction",
1479
            passphrase: "password"
1480
        }, function(err, _wallet) {
1481
            assert.ifError(err);
1482
            assert.ok(_wallet);
1483
1484
            wallet = _wallet;
1485
1486
            client.allWallets({page: 1}, function(err, wallets) {
1487
                assert.ifError(err);
1488
1489
                assert.ok(wallets['data'].length > 0);
1490
1491
                assert.equal(wallet.primaryMnemonic, "give pause forget seed dance crawl situate hole keen");
1492
                assert.equal(wallet.identifier, "unittest-transaction");
1493
                assert.equal(wallet.getBlocktrailPublicKey("M/9999'").toBase58(), "tpubD9q6vq9zdP3gbhpjs7n2TRvT7h4PeBhxg1Kv9jEc1XAss7429VenxvQTsJaZhzTk54gnsHRpgeeNMbm1QTag4Wf1QpQ3gy221GDuUCxgfeZ");
1494
1495
                cb();
1496
            });
1497
        });
1498
    });
1499
1500
    it("should list expected transactions", function(cb) {
1501
        wallet.transactions({page: 1, limit: 23}, function(err, transactions) {
1502
            assert.ifError(err);
1503
            assert.ok(transactions['data']);
1504
            assert.ok(transactions['total']);
1505
            assert.ok(transactions['data'].length === 23);
1506
            assert.ok(transactions['data'][0]['hash'], "2cb21783635a5f22e9934b8c3262146b42d251dfb14ee961d120936a6c40fe89");
1507
1508
            cb();
1509
        });
1510
    });
1511
1512
    it("should list expected addresses", function(cb) {
1513
        wallet.addresses({page: 1, limit: 23}, function(err, addresses) {
1514
            assert.ifError(err);
1515
            assert.ok(addresses['data']);
1516
            assert.ok(addresses['total']);
1517
            assert.ok(addresses['data'].length === 23);
1518
            assert.ok(addresses['data'][0]['address'], "2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS");
1519
1520
            cb();
1521
        });
1522
    });
1523
1524
    it("should list UTXOs", function(cb) {
1525
        wallet.utxos({page: 0, limit: 23}, function(err, addresses) {
1526
            assert.ifError(err);
1527
            assert.ok(addresses['data']);
1528
            assert.ok(addresses['total']);
1529
            assert.ok(addresses['data'].length === 23);
1530
1531
            cb();
1532
        });
1533
    });
1534
});
1535
1536
describe("size estimation", function() {
1537
1538
    it("should estimate proper size for 1 input 1 output TX", function() {
1539
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1540
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
1541
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1542
1543
        assert.equal(347, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1544
    });
1545
1546
    it("should estimate proper size for 99 inputs 1 output TX", function() {
1547
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1548
        for (var i = 0; i < 99; i++) {
1549
            txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', i);
1550
        }
1551
        txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1552
1553
        assert.equal(29453, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1554
    });
1555
1556
    it("should estimate proper size for 1 input 99 outputs TX", function() {
1557
        var txb = new bitcoin.TransactionBuilder(bitcoin.networks.testnet);
1558
        txb.addInput('4200000000000000000000000000000000000000000000000000000000000000', 0);
1559
        for (var i = 0; i < 99; i++) {
1560
            txb.addOutput('2MzyKviSL6pnWxkbHV7ecFRE3hWKfzmT8WS', 1);
1561
        }
1562
1563
        assert.equal(3679, blocktrail.Wallet.estimateIncompleteTxSize(txb.buildIncomplete()));
1564
    });
1565
});
1566
1567
describe("APIClient", function() {
1568
    it("resolvePrimaryPrivateKeyFromOptions", function(cb) {
1569
        client.resolvePrimaryPrivateKeyFromOptions({
1570
            passphrase: "password",
1571
            primaryMnemonic: "give pause forget seed dance crawl situate hole keen"
1572
        }, function(err, options) {
1573
            assert.ifError(err);
1574
            assert.ok(options.primaryPrivateKey);
1575
            assert.ok(options.primaryPrivateKey instanceof bitcoin.HDNode);
1576
            assert.equal("tprv8ZgxMBicQKsPeR93md5eVTbLDgQ8kfV4CDNtrVXv5p29KXtx7VHKFQThGkFgC61sYeeeaVH1yFv4thcvxS9cYdFrYwTNmkGhkQEJycSzAhE", options.primaryPrivateKey.toBase58());
1577
1578
            cb();
1579
1580
        });
1581
    });
1582
});
1583